import os
from werkzeug.utils import secure_filename

from flask import Blueprint, request, session, render_template

from auth import login_required, admin_required
from config import Config
from logger_config import get_logger
from services.agent_service import agent_service
from services.query_service import query_service
from utils.response_utils import create_api_response
from utils.session_utils import get_session_id

logger = get_logger(__name__)

# 创建代理蓝图
agent_bp = Blueprint('agent', __name__, url_prefix='/agent')


@agent_bp.route('/initialize', methods=['POST'])
@login_required
def initialize_agent():
    """初始化代理实例"""
    try:
        data = request.get_json()

        # 验证必需参数
        required_fields = ['api_key', 'base_url', 'llm_model', 'data_path']
        for field in required_fields:
            if not data or field not in data or not data[field]:
                return create_api_response(
                    None,
                    success=False,
                    message=f"缺少必需参数: {field}",
                    status_code=400
                )

        api_key = data['api_key']
        base_url = data['base_url']
        llm_model = data['llm_model']
        data_path = data['data_path']

        # 验证模型是否支持
        if not agent_service.validate_model_support(llm_model):
            return create_api_response(
                None,
                success=False,
                message=f"不支持的模型: {llm_model}",
                status_code=400
            )

        # 验证数据路径是否存在
        if not os.path.exists(data_path):
            return create_api_response(
                None,
                success=False,
                message=f"数据路径不存在: {data_path}",
                status_code=400
            )

        # 创建代理实例
        session_id, agent = agent_service.create_agent_instance(
            api_key, base_url, llm_model, data_path
        )

        # 更新会话信息
        session['session_id'] = session_id
        session['llm_model'] = llm_model
        session['data_path'] = data_path

        logger.info(f"代理初始化成功 - 用户: {session.get('user_id')}, 模型: {llm_model}")

        return create_api_response({
            'session_id': session_id,
            'model': llm_model,
            'data_path': data_path,
            'platform': agent_service.get_model_platform(llm_model)
        }, message="代理初始化成功")

    except Exception as e:
        logger.error(f"代理初始化失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"代理初始化失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/query', methods=['POST'])
@login_required
def process_query():
    """处理查询请求"""
    try:
        data = request.get_json()

        if not data or 'query' not in data or not data['query'].strip():
            return create_api_response(
                None,
                success=False,
                message="请提供查询内容",
                status_code=400
            )

        query_text = data['query'].strip()
        model = data.get('model', '')  # 获取模型参数
        user_id = session.get('user_id')
        session_id = get_session_id()

        # 检查代理是否已初始化
        if not session_id or not agent_service.get_agent_instance(session_id):
            return create_api_response(
                None,
                success=False,
                message="代理未初始化，请先初始化代理",
                status_code=400
            )

        # 处理查询
        result = query_service.process_query(user_id, query_text, session_id, model)

        if result['success']:
            return create_api_response({
                'query_id': result['query_id'],
                'result': result['result'],
                'execution_summary': result['execution_summary'],
                'cost_info': result['cost_info'],
                'execution_time': result['execution_time']
            }, message="查询处理成功")
        else:
            return create_api_response(
                None,
                success=False,
                message=result['error'],
                status_code=400
            )

    except Exception as e:
        logger.error(f"查询处理失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"查询处理失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/status', methods=['GET'])
@login_required
def get_agent_status():
    """获取代理状态"""
    try:
        session_id = get_session_id()

        if not session_id:
            return create_api_response({
                'initialized': False,
                'session_id': None,
                'model': None,
                'data_path': None
            })

        agent = agent_service.get_agent_instance(session_id)

        if not agent:
            return create_api_response({
                'initialized': False,
                'session_id': session_id,
                'model': None,
                'data_path': None
            })

        # 获取会话信息
        model = session.get('llm_model')
        data_path = session.get('data_path')

        return create_api_response({
            'initialized': True,
            'session_id': session_id,
            'model': model,
            'data_path': data_path,
            'platform': agent_service.get_model_platform(model) if model else None
        })

    except Exception as e:
        logger.error(f"获取代理状态失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"获取代理状态失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/reset', methods=['POST'])
@login_required
def reset_agent():
    """重置代理实例"""
    try:
        session_id = get_session_id()

        if session_id:
            # 移除现有代理实例
            agent_service.remove_agent_instance(session_id)

            # 清除会话中的代理相关信息
            session.pop('session_id', None)
            session.pop('llm_model', None)
            session.pop('data_path', None)

            logger.info(f"代理重置成功 - 用户: {session.get('user_id')}, 会话: {session_id}")

        return create_api_response(None, message="代理重置成功")

    except Exception as e:
        logger.error(f"代理重置失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"代理重置失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/auto-initialize', methods=['POST'])
@login_required
def auto_initialize_agent():
    """自动初始化代理（使用默认配置）"""
    try:
        # 使用代理服务的自动初始化功能
        session_id = agent_service.auto_initialize_service()

        if not session_id:
            return create_api_response(
                None,
                success=False,
                message="自动初始化失败，请检查配置或手动初始化",
                status_code=400
            )

        # 更新会话信息
        config = Config()
        session['session_id'] = session_id
        session['llm_model'] = config.DEFAULT_MODEL
        session['data_path'] = config.DATA_PATH

        logger.info(f"代理自动初始化成功 - 用户: {session.get('user_id')}, 模型: {config.DEFAULT_MODEL}")

        return create_api_response({
            'session_id': session_id,
            'model': config.DEFAULT_MODEL,
            'data_path': config.DATA_PATH,
            'platform': agent_service.get_model_platform(config.DEFAULT_MODEL)
        }, message="代理自动初始化成功")

    except Exception as e:
        logger.error(f"代理自动初始化失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"代理自动初始化失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/sessions', methods=['GET'])
@admin_required
def get_all_sessions():
    """获取所有活跃会话（管理员）"""
    try:
        sessions = agent_service.get_all_sessions()
        session_count = agent_service.get_session_count()

        return create_api_response({
            'sessions': sessions,
            'total_count': session_count
        })

    except Exception as e:
        logger.error(f"获取会话列表失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"获取会话列表失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/sessions/<session_id>', methods=['DELETE'])
@admin_required
def remove_session(session_id):
    """移除指定会话（管理员）"""
    try:
        success = agent_service.remove_agent_instance(session_id)

        if success:
            return create_api_response(None, message="会话移除成功")
        else:
            return create_api_response(
                None,
                success=False,
                message="会话不存在或移除失败",
                status_code=404
            )

    except Exception as e:
        logger.error(f"移除会话失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"移除会话失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/upload-file', methods=['POST'])
@login_required
def upload_file():
    """上传文件到会话工作目录"""
    try:
        session_id = get_session_id()
        
        if not session_id:
            return create_api_response(
                None,
                success=False,
                message="会话未初始化，请先初始化代理",
                status_code=400
            )
        
        # 检查代理是否已初始化
        agent = agent_service.get_agent_instance(session_id)
        logger.info(f"[DEBUG] 文件上传 - session_id: {session_id}, agent实例: {agent is not None}")
        if not agent:
            logger.warning(f"代理未初始化 - session_id: {session_id}，尝试自动初始化")
            
            # 尝试自动初始化代理
            try:
                auto_session_id = agent_service.auto_initialize_service()
                if auto_session_id:
                    # 重要：更新Flask session中的session_id，确保与自动初始化的session_id一致
                    config = Config()
                    session['session_id'] = auto_session_id
                    session['llm_model'] = config.DEFAULT_MODEL
                    session['data_path'] = config.DATA_PATH
                    
                    # 重新获取代理实例
                    agent = agent_service.get_agent_instance(auto_session_id)
                    session_id = auto_session_id  # 更新session_id
                    logger.info(f"代理自动初始化成功 - 新session_id: {session_id}，已更新Flask session")
                else:
                    return create_api_response(
                        None,
                        success=False,
                        message="代理未初始化且自动初始化失败，请手动初始化代理",
                        status_code=400
                    )
            except Exception as e:
                logger.error(f"自动初始化失败: {str(e)}")
                return create_api_response(
                    None,
                    success=False,
                    message="代理未初始化且自动初始化失败，请手动初始化代理",
                    status_code=400
                )
        
        # 确保代理实例存在
        if not agent:
            return create_api_response(
                None,
                success=False,
                message="代理初始化失败，请重试",
                status_code=400
            )
        
        # 检查是否有文件上传
        if 'file' not in request.files:
            return create_api_response(
                None,
                success=False,
                message="没有选择文件",
                status_code=400
            )
        
        file = request.files['file']
        
        # 检查文件名
        if file.filename == '':
            return create_api_response(
                None,
                success=False,
                message="没有选择文件",
                status_code=400
            )
        
        # 安全的文件名
        filename = secure_filename(file.filename)
        
        # 检查文件类型（可选）
        allowed_extensions = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'csv', 'json', 'xlsx', 'xls', 'fasta', 'fastq', 'vcf', 'tsv'}
        if '.' in filename:
            file_ext = filename.rsplit('.', 1)[1].lower()
            if file_ext not in allowed_extensions:
                return create_api_response(
                    None,
                    success=False,
                    message=f"不支持的文件类型: {file_ext}。支持的类型: {', '.join(allowed_extensions)}",
                    status_code=400
                )
        
        # 获取会话工作目录
        user_id = session.get('user_id')
        from services.query_service import QueryService
        query_service_instance = QueryService()
        work_dir = query_service_instance._prepare_session_work_directory(user_id, session_id)
        
        # 保存文件
        file_path = os.path.join(work_dir, filename)
        
        # 检查文件是否已存在
        if os.path.exists(file_path):
            return create_api_response(
                None,
                success=False,
                message=f"文件 {filename} 已存在",
                status_code=400
            )
        
        file.save(file_path)
        
        # 获取文件信息
        file_size = os.path.getsize(file_path)
        
        logger.info(f"文件上传成功: {filename}, 大小: {file_size} bytes, 路径: {file_path}")
        
        return create_api_response({
            'filename': filename,
            'file_path': file_path,
            'file_size': file_size,
            'work_directory': work_dir,
            'session_id': session_id  # 添加session_id到响应中
        }, message=f"文件 {filename} 上传成功")
        
    except Exception as e:
        logger.error(f"文件上传失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"文件上传失败: {str(e)}"
        )
        response.status_code = 500
        return response


@agent_bp.route('/files', methods=['GET'])
@login_required
def list_files():
    """列出会话工作目录中的文件"""
    try:
        session_id = get_session_id()
        
        if not session_id:
            return create_api_response(
                None,
                success=False,
                message="会话未初始化",
                status_code=400
            )
        
        # 获取会话工作目录
        user_id = session.get('user_id')
        from services.query_service import QueryService
        query_service_instance = QueryService()
        work_dir = query_service_instance._prepare_session_work_directory(user_id, session_id)
        
        files = []
        if os.path.exists(work_dir):
            for filename in os.listdir(work_dir):
                file_path = os.path.join(work_dir, filename)
                if os.path.isfile(file_path):
                    file_info = {
                        'name': filename,
                        'size': os.path.getsize(file_path),
                        'modified': os.path.getmtime(file_path)
                    }
                    files.append(file_info)
        
        return create_api_response({
            'files': files,
            'work_directory': work_dir,
            'file_count': len(files)
        })
        
    except Exception as e:
        logger.error(f"获取文件列表失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"获取文件列表失败: {str(e)}"
        )
        response.status_code = 500
        return response


@agent_bp.route('/files/<filename>', methods=['DELETE'])
@login_required
def delete_file(filename):
    """删除会话工作目录中的文件"""
    try:
        session_id = get_session_id()
        
        if not session_id:
            return create_api_response(
                None,
                success=False,
                message="会话未初始化",
                status_code=400
            )
        
        # 安全的文件名
        safe_filename = secure_filename(filename)
        
        # 获取会话工作目录
        user_id = session.get('user_id')
        from services.query_service import QueryService
        query_service_instance = QueryService()
        work_dir = query_service_instance._prepare_session_work_directory(user_id, session_id)
        
        file_path = os.path.join(work_dir, safe_filename)
        
        if not os.path.exists(file_path):
            return create_api_response(
                None,
                success=False,
                message=f"文件 {safe_filename} 不存在",
                status_code=404
            )
        
        if not os.path.isfile(file_path):
            return create_api_response(
                None,
                success=False,
                message=f"{safe_filename} 不是文件",
                status_code=400
            )
        
        os.remove(file_path)
        
        logger.info(f"文件删除成功: {safe_filename}")
        
        return create_api_response(
            None,
            message=f"文件 {safe_filename} 删除成功"
        )
        
    except Exception as e:
        logger.error(f"删除文件失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"删除文件失败: {str(e)}"
        )
        response.status_code = 500
        return response


@agent_bp.route('/models/validate', methods=['POST'])
@login_required
def validate_model():
    """验证模型是否支持"""
    try:
        data = request.get_json()

        if not data or 'model_name' not in data:
            return create_api_response(
                None,
                success=False,
                message="请提供模型名称",
                status_code=400
            )

        model_name = data['model_name']
        is_supported = agent_service.validate_model_support(model_name)
        platform = agent_service.get_model_platform(model_name)

        return create_api_response({
            'model_name': model_name,
            'supported': is_supported,
            'platform': platform
        })

    except Exception as e:
        logger.error(f"验证模型失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"验证模型失败: {str(e)}"
        )

        response.status_code = 500

        return response


@agent_bp.route('/config/check', methods=['POST'])
@login_required
def check_agent_config():
    """检查代理配置"""
    try:
        data = request.get_json()

        if not data:
            return create_api_response(
                None,
                success=False,
                message="请提供配置信息",
                status_code=400
            )

        api_key = data.get('api_key')
        base_url = data.get('base_url')
        llm_model = data.get('llm_model')
        data_path = data.get('data_path')

        # 检查结果
        checks = {
            'api_key': {
                'valid': bool(api_key and api_key.strip() and api_key != 'your_api_key_here'),
                'message': '有效的API密钥' if api_key and api_key.strip() and api_key != 'your_api_key_here' else 'API密钥无效或未设置'
            },
            'base_url': {
                'valid': bool(base_url and base_url.strip()),
                'message': '有效的基础URL' if base_url and base_url.strip() else '基础URL未设置'
            },
            'model': {
                'valid': agent_service.validate_model_support(llm_model) if llm_model else False,
                'message': f'支持的模型: {llm_model}' if llm_model and agent_service.validate_model_support(
                    llm_model) else f'不支持的模型: {llm_model}' if llm_model else '未选择模型'
            },
            'data_path': {
                'valid': os.path.exists(data_path) if data_path else False,
                'message': '数据路径存在' if data_path and os.path.exists(
                    data_path) else f'数据路径不存在: {data_path}' if data_path else '数据路径未设置'
            }
        }

        # 总体有效性
        all_valid = all(check['valid'] for check in checks.values())

        return create_api_response({
            'valid': all_valid,
            'checks': checks,
            'message': '配置检查完成' if all_valid else '配置存在问题，请检查'
        })

    except Exception as e:
        logger.error(f"检查代理配置失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"检查代理配置失败: {str(e)}"
        )

        response.status_code = 500

        return response


# 页面路由
@agent_bp.route('/dashboard')
@login_required
def agent_dashboard():
    """代理控制面板页面"""
    try:
        # 获取代理状态
        session_id = get_session_id()
        agent_initialized = bool(session_id and agent_service.get_agent_instance(session_id))

        # 获取配置信息
        config = Config()

        return render_template('agent/dashboard.html',
                               agent_initialized=agent_initialized,
                               session_id=session_id,
                               current_model=session.get('llm_model'),
                               current_data_path=session.get('data_path'),
                               supported_models=list(config.MODEL_PLATFORM_MAP.keys()),
                               default_model=config.DEFAULT_MODEL,
                               default_data_path=config.DATA_PATH)

    except Exception as e:
        logger.error(f"加载代理控制面板失败: {str(e)}")
        return render_template('error.html',
                               error_message=f"加载代理控制面板失败: {str(e)}"), 500


@agent_bp.route('/query-interface')
@login_required
def query_interface():
    """查询界面页面"""
    try:
        # 检查代理是否已初始化
        session_id = get_session_id()
        agent_initialized = bool(session_id and agent_service.get_agent_instance(session_id))

        if not agent_initialized:
            return render_template('agent/not_initialized.html')

        return render_template('agent/query.html',
                               session_id=session_id,
                               current_model=session.get('llm_model'),
                               current_data_path=session.get('data_path'))

    except Exception as e:
        logger.error(f"加载查询界面失败: {str(e)}")
        return render_template('error.html',
                               error_message=f"加载查询界面失败: {str(e)}"), 500
